<?php
/**
 * (logic)
 */
namespace App\Logic\MonthlyReport;

use App\Models\Basics\SysICountry;
use App\Models\Basics\SysPlat;
use App\Models\Delivery\FBADelivery;
use App\Models\CustomerDelivery\CustomerDelivery;
use App\Models\MonthlyReport\Cost\LogisticsBalance;
use App\Models\MonthlyReport\Cost\LogisticsOSBalance;
use App\Models\MonthlyReport\Cost\LSaleOSRecord;
use App\Models\MonthlyReport\Tmp\TmpPSales;
use App\Models\OverSeasIn\Delivery as OSDelivery;
use App\Models\OverSeasOut\FBADelivery as OSFBADelivery;
use App\Models\OverSeasOut\RemovaleDelivery;
use Illuminate\Support\Facades\DB;
class CheckLogisticsBalance
{
    public static function exe($func)
    {
        try{
            DB::beginTransaction();
            self::{$func}();
            DB::commit();
        }catch (\Exception $e){
            DB::rollBack();
            report($e);
        }
    }

    /**
     * 5.新版小包发货出仓
     * 'AU','AE','MX','BR'订单
     */
    private static function _exeCustomerPlacing(){
        $orderIds = TmpPSales::query()
            ->where('type','Order')
            ->whereNotNull('sku')
            ->whereIn('country',['AU','AE','MX','BR'])
            ->groupBy('order_id')
            ->pluck('order_id');
        $area = [];
        $pds = CustomerDelivery::with('detail')
            ->whereIn('order_no',$orderIds)
            ->where('delivery_type',3)
            ->where('logistics_status',2)
            ->where('logistics_check_status',0)
            ->orderBy('delivered_at','ASC')
            ->get();
        foreach ($pds as $pd){
            if(!array_key_exists($pd->country_id,$area)){
                $area[$pd->country_id] = SysICountry::getAreaIdByCountryId($pd->country_id);
            }
            $areaId = $area[$pd->country_id];
            foreach ($pd->detail as $pdd){
                if($pdd->ship_num == 0)continue;
                $count = LogisticsBalance::query()
                    ->where('area_id' , $areaId)
                    ->where('psku_id' , $pdd->psku_id)
                    ->where('delivery_no' , $pd->delivery_no)
                    ->count();
                if($count > 0)continue;
                LogisticsBalance::query()->create(
                    [
                        'area_id' => $areaId,
                        'psku_id' => $pdd->psku_id,
                        'delivery_no' => $pd->delivery_no,
                        'delivered_at' => $pd->delivered_at,
                        'b_num' => $pdd->ship_num,
                        'b_price' => $pdd->logistics_fee ?: 0,
                        'b_balance_sale' => $pdd->ship_num,
                    ]
                );
            }
        }
    }

    /**
     * 4.国内仓发往FBA
     */
    private static function _exePlacing(){
        $ds = FBADelivery::with('detail')
            ->where('status',6)//已发货
            ->where('logistics_status',2)//运费已更新
            ->where('logistics_fee_status',0)//未纳入统计
            ->where('logistics_check_status',0)//运费核算状态正常
            ->orderBy('delivered_at','ASC')
            ->get();
        foreach ($ds as $d){
            foreach ($d->detail as $item){
                if($item->ship_num == 0)continue;
                $count = LogisticsBalance::query()
                    ->where('area_id' , $d->area_id)
                    ->where('psku_id' , $item->psku_id)
                    ->where('delivery_no' , $d->delivery_no)
                    ->count();
                if($count > 0)continue;
                LogisticsBalance::query()->create(
                    [
                        'area_id' => $d->area_id,
                        'psku_id' => $item->psku_id,
                        'delivery_no' => $d->delivery_no,
                        'delivered_at' => $d->delivered_at,
                        'b_num' => $item->ship_num,
                        'b_price' => $item->logistics_fee ?: 0,
                        'b_balance_sale' => $item->ship_num,
                    ]
                );
            }
            $d->logistics_fee_status = 1;
            $d->save();
        }
    }

    /**
     * 3.海外仓移库发往FBA
     */
    private static function _exeRemovalePlacing(){
        $ds = RemovaleDelivery::with('detail')
            ->where('status',4)//已发货
            ->where('logistics_status',2)//运费已更新
            ->where('logistics_fee_status',0)//未纳入统计
            ->where('logistics_check_status',0)//运费核算状态正常
            ->orderBy('delivered_at','ASC')
            ->get();
        foreach ($ds as $d){
            foreach ($d->detail as $item){
                if($item->ship_num == 0)continue;
                $count = LogisticsBalance::query()
                    ->where('area_id' , $d->area_id)
                    ->where('psku_id' , $item->psku_id)
                    ->where('delivery_no' , $d->delivery_no)
                    ->count();
                if($count > 0)continue;
                LogisticsBalance::query()->create(
                    [
                        'area_id' => $d->area_id,
                        'psku_id' => $item->psku_id,
                        'delivery_no' => $d->delivery_no,
                        'delivered_at' => $d->delivered_at,
                        'b_num' => $item->ship_num,
                        'b_price' => $item->logistics_fee ?: 0,
                        'b_balance_sale' => $item->ship_num,
                    ]
                );
            }
            $d->logistics_fee_status = 1;
            $d->save();
        }
    }

    /**
     * 2.国内仓发往海外仓代发
     * @return void
     */
    private static function _exePlacingOSDropShipping(){
        $ds = OSDelivery::with('detail')
            ->where('plat_id',SysPlat::PLAT_AMAZON)
            ->where('delivery_type',OSDelivery::OS_DELIVERY_DROPSHIPPING)
            ->where('status','>=',6)//已发货或已入海外仓中转仓
            ->where('logistics_status',2)//运费已更新
            ->where('logistics_fee_status',0)//未纳入统计
            ->where('logistics_check_status',0)//运费核算状态正常
            ->orderBy('delivered_at','ASC')
            ->get();
        foreach ($ds as $d){
            foreach ($d->detail as $item){
                if($item->ship_num == 0)continue;
                $count = LogisticsBalance::query()
                    ->where('area_id' , $d->area_id)
                    ->where('psku_id' , $item->psku_id)
                    ->where('delivery_no' , $d->delivery_no)
                    ->count();
                if($count > 0)continue;
                LogisticsBalance::query()->create(
                    [
                        'area_id' => $d->area_id,
                        'psku_id' => $item->psku_id,
                        'delivery_no' => $d->delivery_no,
                        'delivered_at' => $d->delivered_at,
                        'b_num' => $item->ship_num,
                        'b_price' => $item->logistics_fee ?: 0,
                        'b_balance_sale' => $item->ship_num,
                    ]
                );
            }
            $d->logistics_fee_status = 1;
            $d->save();
        }
    }

    /**
     * 1.2.海外仓中转发往FBA（海外仓中转-入仓：头程 + 海外仓中转-出仓：尾程）
     */
    private static function _exePlacingOSFBA(){
        $ds = OSFBADelivery::with('detail')
            ->where('status',3)//已发货
            ->where('logistics_status',2)//运费已更新
            ->where('logistics_fee_status',0)//未纳入统计
            ->where('logistics_check_status',0)//运费核算状态正常
            ->orderBy('delivered_at','ASC')
            ->get();
        foreach ($ds as $d){
            foreach ($d->detail as $item){
                if($item->ship_num == 0)continue;
                $mix = LogisticsOSBalance::query()
                    ->where('area_id',$d->area_id)
                    ->where('psku_id',$item->psku_id)
                    ->where('b_balance_sale','>',0)
                    ->where('delivered_at','<=',$d->delivered_at)
                    ->orderBy('delivered_at','ASC')
                    ->get();
                $needDis = $item->ship_num;
                $sum = 0;
                if($mix->isEmpty()){
                    $fBalanceEmpty = LogisticsOSBalance::query()
                        ->where('area_id',$d->area_id)
                        ->where('psku_id',$item->psku_id)
                        ->where('delivered_at','<=',$d->delivered_at)
                        ->orderBy('delivered_at','DESC')
                        ->first();
                    if($fBalanceEmpty){
                        $sum = $fBalanceEmpty->b_price * $needDis;
                        LSaleOSRecord::query()->create([
                            'area_id' => $d->area_id,
                            'psku_id' => $item->psku_id,
                            'delivery_no' => $fBalanceEmpty->delivery_no,
                            'b_num' => $needDis,
                            'b_balance' => $fBalanceEmpty->b_balance_sale,
                        ]);
                    }
                }else{
                    foreach($mix as $_mix){
                        if($needDis == 0)break;
                        $min = min($needDis,$_mix->b_balance_sale);
                        $needDis -= $min;
                        $_mix->b_balance_sale -= $min;
                        $_mix->save();
                        LSaleOSRecord::query()->create([
                            'area_id' => $d->area_id,
                            'psku_id' => $item->psku_id,
                            'delivery_no' => $_mix->delivery_no,
                            'b_num' => $min,
                            'b_balance' => $_mix->b_balance_sale,
                        ]);
                        $sum += $min * ($_mix->b_price ?? 0);
                    }
                    if($needDis > 0){
                        $fBalance = LogisticsOSBalance::query()
                            ->where('area_id',$d->area_id)
                            ->where('psku_id',$item->psku_id)
                            ->where('delivered_at','<=',$d->delivered_at)
                            ->orderBy('delivered_at','DESC')
                            ->first();
                        if($fBalance){
                            $sum += $fBalance->b_price * $needDis;
                            LSaleOSRecord::query()->create([
                                'area_id' => $d->area_id,
                                'psku_id' => $item->psku_id,
                                'delivery_no' => $fBalance->delivery_no,
                                'b_num' => $needDis,
                                'b_balance' => $fBalance->b_balance_sale,
                            ]);
                        }
                    }
                }
                $sum += $item->ship_num * ($item->logistics_fee ?: 0);
                $price = round($sum / $item->ship_num,3);
                LogisticsBalance::query()->updateOrCreate(
                    [
                        'area_id' => $d->area_id,
                        'psku_id' => $item->psku_id,
                        'delivery_no' => $d->delivery_no,
                    ],
                    [
                        'delivered_at' => $d->delivered_at,
                        'b_num' => $item->ship_num,
                        'b_price' => $price,
                        'b_balance_sale' => $item->ship_num,
                    ]
                );
            }
            $d->logistics_fee_status = 1;
            $d->save();
        }
    }

    /**
     * 1.1.国内仓发往海外仓中转（海外仓中转-入仓:头程）
     */
    private static function _exePlacingOS(){
        $ds = OSDelivery::with('detail')
            ->where('plat_id',SysPlat::PLAT_AMAZON)
            ->where('delivery_type',OSDelivery::OS_DELIVERY_TRANSFER)
            ->where('status','>=',6)//已发货或已入海外仓中转仓
            ->where('logistics_status',2)//运费已更新
            ->where('logistics_fee_status',0)//未纳入统计
            ->where('logistics_check_status',0)//运费核算状态正常
            ->orderBy('delivered_at','ASC')
            ->get();
        foreach ($ds as $d){
            foreach ($d->detail as $item){
                if($item->ship_num == 0)continue;
                $count = LogisticsOSBalance::query()
                    ->where('area_id' , $d->area_id)
                    ->where('psku_id' , $item->psku_id)
                    ->where('delivery_no' , $d->delivery_no)
                    ->count();
                if($count > 0)continue;
                LogisticsOSBalance::query()->create([
                    'area_id' => $d->area_id,
                    'psku_id' => $item->psku_id,
                    'delivery_no' => $d->delivery_no,
                    'delivered_at' => $d->delivered_at,
                    'b_num' => $item->ship_num,
                    'b_price' => $item->logistics_fee ?: 0,
                    'b_balance_sale' => $item->ship_num,
                ]);
            }
            $d->logistics_fee_status = 1;
            $d->save();
        }
    }
}
